//
//  MFAPMRequestManager.m
//  MFAPMManager
//
//  Created by zhang liyu on 2019/6/13.
//

#import "MFAPMRequestManager.h"

#import "MFAFNetworking/MFAFNetworking.h"
#import "MFEncryption/MFAESEncryptor.h"
#import "MFEncryption/MFRSA.h"

#import "UIDevice+MFAPMUtility.h"
#import "MFAPMUtility.h"
#import "MFAPMDefine.h"

@interface MFAPMRequestManager ()

@property (nonatomic, strong) MFAFHTTPSessionManager *getManager;
@property (nonatomic, strong) MFAFHTTPSessionManager *postManager;

@property (nonatomic, assign) BOOL isEncrypt;

@end

@implementation MFAPMRequestManager

#pragma mark - Singleton

+ (instancetype)sharedInstance{
    static MFAPMRequestManager *requestManager = nil;
    static dispatch_once_t onceToken;
    dispatch_once(&onceToken, ^{
        requestManager = [[MFAPMRequestManager alloc] init];
    });
    return requestManager;
}

#pragma mark - Request Actions

+ (void)GET:(NSString *)urlStr parametersDict:(NSDictionary *)parametersDict success:(void (^)(NSURLSessionDataTask * _Nonnull task, id  _Nullable responseObject))success failure:(void (^)(NSURLSessionDataTask * _Nullable task, NSError * _Nonnull error))failure{
    
    //生成请求所需的参数
    NSString *requestURLStr = [[MFAPMRequestManager sharedInstance] configRequestUrl:urlStr];
    NSDictionary *paramDict = [[MFAPMRequestManager sharedInstance] configGETReqeustParamDict:parametersDict];;

    [[MFAPMRequestManager sharedInstance].getManager GET:requestURLStr
                                              parameters:paramDict
                                                progress:nil
                                                 success:success
                                                 failure:failure];
}

+ (void)POST:(NSString *)urlStr parametersDict:(NSDictionary *)parametersDict success:(void (^)(NSURLSessionDataTask * _Nonnull task, id  _Nullable responseObject))success failure:(void (^)(NSURLSessionDataTask * _Nullable task, NSError * _Nonnull error))failure{
    
    //生成请求所需的参数
    NSString *requestURLStr = [[MFAPMRequestManager sharedInstance] configRequestUrl:urlStr];
    NSDictionary *paramDict = [[MFAPMRequestManager sharedInstance] configPOSTReqeustParamDict:parametersDict];;

    [[MFAPMRequestManager sharedInstance].postManager POST:requestURLStr
                                                parameters:paramDict
                                                  progress:nil
                                                   success:success
                                                   failure:failure];
}

#pragma mark - Parameter Config Actions

- (NSString *)configRequestUrl:(NSString *)URLString {
    
    //暂时需要拼接url进行请求，后续若需进行完全url判断时打开
//    NSURL *originalURL = [NSURL URLWithString:URLString];
//    // 如果用户传入的url是带host的全路径地址
//    if (originalURL && originalURL.host && originalURL.scheme) {
//        return [URLString stringByAddingPercentEncodingWithAllowedCharacters:[NSCharacterSet URLQueryAllowedCharacterSet]] ? : @"";
//    }
    //根据baseUrl拼接路径
    NSString *requestURLStr = [[NSString stringWithFormat:@"%@%@", MFAPM_REQUEST_BASE_URL_STRING, URLString] stringByAddingPercentEncodingWithAllowedCharacters:[NSCharacterSet URLQueryAllowedCharacterSet]] ? : @"";
    return [requestURLStr copy];
}

- (NSDictionary *)configGETReqeustParamDict:(NSDictionary *)parameterDict{
    
    return [[MFAPMRequestManager sharedInstance] configParametersDict:parameterDict forRequestManager:[MFAPMRequestManager sharedInstance].getManager];
}

- (NSDictionary *)configPOSTReqeustParamDict:(NSDictionary *)parameterDict{

    return [[MFAPMRequestManager sharedInstance] configParametersDict:parameterDict forRequestManager:[MFAPMRequestManager sharedInstance].postManager];
}


- (NSDictionary *)configParametersDict:(NSDictionary *)parameterDict
                     forRequestManager:(MFAFHTTPSessionManager *)manager{
    //非加密，直接返回参数字典
    if(![MFAPMRequestManager sharedInstance].isEncrypt){
        return [NSDictionary dictionaryWithDictionary:parameterDict];
    }
    
    //加密请求参数配置
    
    //获取AES对称秘钥
    NSString *key = [MFAPMRequestManager sharedInstance].configEncryptKey;
    //RSA加密后的AES秘钥
    NSString *rsaKey = [MFRSA encryptString:key publicKey:MFAPM_REQUEST_ENCRYPT_RSA_PUB_KEY];
    //设置RSA加密后的AES秘钥到header
    [manager.requestSerializer setValue:rsaKey forHTTPHeaderField:@"sign"];
    
    //将参数字典转为Data
    NSData *paramData = [MFAPMUtility convertDataFromDictionary:parameterDict];
    //将data转化为base64字符串
    NSString *paramBase64Str = [[NSString alloc] initWithData:[paramData base64EncodedDataWithOptions:0] encoding:NSUTF8StringEncoding];
    //使用对称秘钥key将参数Data转为AES加密串
    NSString *paramAESStr = [MFAESEncryptor ecb_pkcs5_encryptedStringWithPlain:paramBase64Str key:key];
    //加密后的参数字典
    NSDictionary *paramDict = @{@"obj" : (paramAESStr ? : @"")};
    
    return [NSDictionary dictionaryWithDictionary:paramDict];
}

- (NSString *)configEncryptKey{
    
    NSString *timeStamp = [NSString stringWithFormat:@"%.0lf",[[NSDate date] timeIntervalSince1970] * 1000];
    NSString *UUID = [UIDevice mfapm_getDeviceUUID];
    
    //生成加密前秘钥
    NSString *originalStr = [NSString stringWithFormat:@"%@%@",[timeStamp substringWithRange:NSMakeRange(timeStamp.length - 8, 8)], [UUID substringToIndex:8]];
    //MD5字符串
    NSString *md5Str = [MFAPMUtility MD5In32BitFromStr:originalStr];
    
    //取0到15作为开始
    NSInteger startPoint = arc4random() % 15;
    //当剩余长度小于16时，取全部剩余子串，否则拿16位作为key
    NSInteger keyLength = (md5Str.length - 1 - startPoint) < 16 ? (md5Str.length - 1 - startPoint) : 16;
    NSString *key = [md5Str substringWithRange:NSMakeRange(startPoint, keyLength)];
    
    return [key copy];
}

#pragma mark - Setter & Getter

- (MFAFHTTPSessionManager *)getManager{
    if(!_getManager){
        _getManager = [MFAFHTTPSessionManager manager];
        
        _getManager.requestSerializer = [MFAFJSONRequestSerializer serializer];
        _getManager.requestSerializer.timeoutInterval = 5.f;
        [_getManager.requestSerializer setValue:MFAPM_REQUEST_ENCRYPT_STATUS forHTTPHeaderField:@"encrypted"];
        
        _getManager.responseSerializer = [MFAFJSONResponseSerializer serializer];
        _getManager.responseSerializer.acceptableContentTypes = [NSSet setWithObjects:@"application/json", @"text/json", @"text/javascript", @"text/html", @"application/x-javascript", nil];
    }
    return _getManager;
}

- (MFAFHTTPSessionManager *)postManager{
    if(!_postManager){
        _postManager = [MFAFHTTPSessionManager manager];
        
        _postManager.requestSerializer = [MFAFJSONRequestSerializer serializer];
        [_postManager.requestSerializer setValue:MFAPM_REQUEST_ENCRYPT_STATUS forHTTPHeaderField:@"encrypted"];
        
        _postManager.responseSerializer = [MFAFJSONResponseSerializer serializer];
        _postManager.responseSerializer.acceptableContentTypes = [NSSet setWithObjects:@"application/json", @"text/json", @"text/javascript", @"text/html", @"application/x-javascript", nil];
    }
    return _postManager;
}

- (BOOL)isEncrypt{
    return [MFAPM_REQUEST_ENCRYPT_STATUS boolValue];
}

@end
